package cn.wjzhang.gen;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileWriter;
import java.util.Date;
import java.util.List;

@Slf4j
public class CodeGenerator {

    public static void main(String[] args) throws Exception {
        CodeGenerator codeGenerater = new CodeGenerator(
                "172.19.19.101", "3306", "root", "Zwj1996@", "wj_db","wj-middle",
//                "E:\\GitCode\\wmc-crm\\wmc-crm-service\\src\\main\\java", "com.altx.crm2",
                "D:\\coding", "cn.wjzhang.middle.modules.word",
                "wjzhang",
                false,//若为true，则生成的controller、service、mapper中无“增删改查”的方法实现
                "com.mysql.jdbc.Driver"
        );
        codeGenerater.generate("mid_word");
    }

    private final String projectName;//代码输出项目名称
    private final String outProjectName;//代码输出项目名称
    private final String prefixPackage;//前缀报名
    private final String author;
    private final Boolean isSimple; //是否只生成简单代码

    private DbUtils dbUtils;

    public CodeGenerator(String host, String port, String username, String password, String dbName,String projectName,
                            String outProjectName, String prefixPackage,
                            String author,
                            Boolean isSimple,
                            String driveName) {
        this.dbUtils = new DbUtils(host, port, username, password, dbName, driveName);
        this.projectName = projectName;
        this.outProjectName = outProjectName;
        this.prefixPackage = prefixPackage;

        this.author = author;
        this.isSimple = isSimple;
    }

    /**
     * 代码生成(批量)
     * @param tbNames 表
     */
    public void generate(String... tbNames) throws Exception {
        for (String tbName : tbNames) {
            generate(tbName);
        }
    }

    /**
     * 代码生成
     * @param tbName 表
     */
    private void generate(String tbName) throws Exception {
        TbInfo tbInfo = this.dbUtils.getTbInfo(tbName);//生成表相关信息
        if (tbInfo != null) {
            tbInfo.setProjectName(this.projectName);
            tbInfo.setApiPath(tbName.replaceAll("_", ""));
            tbInfo.setPrefixPackage(this.prefixPackage);
            tbInfo.setAuthor(this.author);
            tbInfo.setIsSimple(this.isSimple);

            // 文件输出
            this.fileOutput(tbInfo);
        }
    }

    /**
     * 代码生成(可视化)
     * @param tbInfoList 表
     */
    public void generate(List<TbInfo> tbInfoList) throws Exception {
        for (TbInfo tbInfo : tbInfoList) {
            if (tbInfo != null) {
                tbInfo.setProjectName(this.projectName);
                tbInfo.setApiPath(tbInfo.getTbName().replaceAll("_", ""));
                tbInfo.setPrefixPackage(this.prefixPackage);
                tbInfo.setAuthor(this.author);
                tbInfo.setIsSimple(this.isSimple);
                tbInfo.setDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                // 文件输出
                this.fileOutput(tbInfo);
            }
        }
    }

    private void fileOutput(TbInfo tbInfo) throws Exception {
        //直接干到com.altx.crm包下
        String rootPath = this.outProjectName + "/" + this.prefixPackage.replaceAll("\\.", "/");

        //模板目录
//        File directory = new File("src/main/resources");
//        String resourcePath = directory.getCanonicalPath();
//        String templatePath = resourcePath + "/template";
//
//        File file = new File(this.getClass().getResource("").getPath());
//        String codeGeneraterPath = file.getPath();

        // 1.设置配置类
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        //2. 设置模板所在的目录
//        configuration.setDirectoryForTemplateLoading(new File(templatePath));
        configuration.setClassForTemplateLoading(CodeGenerator.class, "/template");
        //3.设置字符集
        configuration.setDefaultEncoding("utf-8");

        //创建文件夹
        String entityPath = rootPath + "/beans/entity";
        String paramPath = rootPath + "/beans/request";
        String dtoPath = rootPath + "/beans/vo";
        String mapperPath = rootPath + "/mapper";
        String mapperXmlPath = rootPath + "/mapper/xml";
        String servicePath = rootPath + "/service";
        String serviceImplPath = rootPath + "/service/impl";
        String controllerPath = rootPath + "/controller";
        String vuePath = this.outProjectName + "/vue";
        String vueModulesPath = this.outProjectName + "/vue/modules";

        FileUtil.mkdir(new File(entityPath));
        FileUtil.mkdir(new File(entityPath));
        FileUtil.mkdir(new File(paramPath));
        FileUtil.mkdir(new File(dtoPath));
        FileUtil.mkdir(new File(mapperPath));
        FileUtil.mkdir(new File(mapperXmlPath));
        FileUtil.mkdir(new File(servicePath));
        FileUtil.mkdir(new File(serviceImplPath));
        FileUtil.mkdir(new File(controllerPath));
        FileUtil.mkdir(new File(vuePath));
        FileUtil.mkdir(new File(vueModulesPath));

        log.info("开始生成 {} - {}", tbInfo.getTbName(), tbInfo.getTbDesc());

        createJavaFile(configuration, "entity", entityPath + "/" + tbInfo.getJavaNameBig() + ".java", tbInfo);
        createJavaFile(configuration, "AddRequest", paramPath + "/" + tbInfo.getJavaNameBig() + "AddRequest.java", tbInfo);
        createJavaFile(configuration, "EditRequest", paramPath + "/" + tbInfo.getJavaNameBig() + "EditRequest.java", tbInfo);
        createJavaFile(configuration, "ListRequest", paramPath + "/" + tbInfo.getJavaNameBig() + "ListRequest.java", tbInfo);
        createJavaFile(configuration, "vo", dtoPath + "/" + tbInfo.getJavaNameBig() + "Vo.java", tbInfo);
        createJavaFile(configuration, "mapper", mapperPath + "/" + tbInfo.getJavaNameBig() + "Mapper.java", tbInfo);
        createJavaFile(configuration, "mapperXml", mapperXmlPath + "/" + tbInfo.getJavaNameBig() + "Mapper.xml", tbInfo);
        createJavaFile(configuration, "service", servicePath + "/" + tbInfo.getJavaNameBig() + "Service.java", tbInfo);
        createJavaFile(configuration, "serviceImpl", serviceImplPath + "/" + tbInfo.getJavaNameBig() + "ServiceImpl.java", tbInfo);
        createJavaFile(configuration, "controller", controllerPath + "/" + tbInfo.getJavaNameBig() + "Controller.java", tbInfo);
        createJavaFile(configuration, "List", vuePath + "/" + tbInfo.getJavaNameBig() + "List.vue", tbInfo);
        createJavaFile(configuration, "Modal", vueModulesPath + "/" + tbInfo.getJavaNameBig() + "Modal.vue", tbInfo);
        createJavaFile(configuration, "Modal_Drawer", vueModulesPath + "/" + tbInfo.getJavaNameBig() + "Modal_Drawer.vue", tbInfo);

        log.info("生成成功 {} - {}", tbInfo.getTbName(), tbInfo.getTbDesc());
    }


    private String createJavaFile(Configuration configuration, String templateName, String savePath, TbInfo tbInfo) throws Exception {
        //4.加载模板
        Template template = configuration.getTemplate(templateName + ".ftl");

        //6.创建Writer对象
        File file = new File(savePath);
        FileWriter writer = new FileWriter(file);
        //7.输出数据模型到文件中
        template.process(tbInfo, writer);
        //8.关闭Writer对象
        writer.close();

        return savePath;
    }
}